Safe Navigation
For Member Access
Accessing deeply nested fields which can potentially be nil was problematic, because you'd need an unreasonable amount of guard clauses to prevent an "attempt to index nil" error. Pluto now offers this syntax:
Basic Usageplutolocal person = {name = "Alice"}local pet_name = person.pet?.name
In this example, person.pet is nil. However, this does not throw an "attempt to index nil" error. pet_name is simply set to nil.
Practical Usagepluto-- Pretend userConfig is parsed from a JSON file, or something.--- Returning the user's preferred color, or Red if they have no preferred color.local function get_color()return userConfig.colors?.preferred ?? "Red"endprint(get_color())
In this example, we also use the null coalescing operator ??.
These cannot be used for statements, like a?.b?.c = 0. They're only valid as expressions.
Safe Navigation (for member access) was written by Sven Olsen.
For Method Calls
Similarly, if you want to have optional hook functions, you can use safe method calls instead of writing conditionals:
Lua Wayplutoif self.onEvent thenself:onEvent(event)end
Pluto Wayplutoself:onEvent?(event)
You can also check if the left-hand side of : is not nil:
plutoobject?:onEvent(event) -- 'object' may be nilobject?:onEvent?(event) -- 'object' and 'object.onEvent' may be nil
Note that this feature will truncate multiple return values if they're not used as part of a fixed assignment:
plutofunction myfunc()return 1, 2endlocal a, b, c = _G:myfunc?()print(a, b, c) --> 1 2 nilprint(_G:myfunc?()) --> 1